package wikibooks;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;

/**
 * Contains settings related to the conversion of MediaWiki markup to LaTeX,
 * such as template and bold text conversion settings. Used in
 * <code>WikibookConverter</code> and <code>WikicodeConverter</code>.
 * Create with default settings using <code>new ConversionSettings()</code>
 * and change settings using public fields and methods if necessary.
 */
public class ConversionSettings {

    /** Width of a line, in number of 'm's. */
    public int textWidth = 43;
    /** Path to downloaded images */
    public String imagepath = "./images/";
    /** The default DPI used if image sizes are specified */
    public int imageDPI = 120;
    /** The default image width use if image sizes are not specified */
    public String imageDefaultWidth = "0.3\\textwidth";
    /** Do not use wrapfigures, use floats instead */
    public boolean noWrapFigs = false;

    /**
     * the String to use to indent LaTeX markup; default is "\t" (a
     * tab); use setIndent(" ") (in javadoc:
     * setIndent("&nbsp;&nbsp;&nbsp;&nbsp;")) to use four spaces as
     * the indent
     */
    private String indent = "\t";
    /**
     * if true and String codeLanguage is not null, converts &lt;pre> text to
     * either the \lstinline|...| command or the lstlisting environment.
     */
    public boolean convertPreToCodeListing = false;
    /**
     * if true and String codeLanguage is not null, converts &lt;pre> text to
     * either the \lstinline|...| command or the lstlisting environment.
     */
    public boolean convertCodeToCodeListing = false;
    /**
     * If true then &lt;source&gt; tag will be converted to \verbatim.
     */
    public boolean convertCodeToPre = true;
    /**
     * The programming language used in code segments
     */
    private String codeLanguage = null;
    /**
     * the command to use for '''bold text'''; default is "textbf"; "emph"
     * recommended if bold is used only for emphasis; if bold is used for a
     * specific function (ie all keywords are bold), consider using a specific
     * logical command (ie "keyword")
     */
    private String boldCommand = "\\textbf";
    /**
     * The images found in the chapter, formatted as "title.extension" (ie:
     * "foo.jpg").
     */
    private HashSet<String> images = new HashSet<String>();
    /**
     * path to file containing project (Wikibooks') logo.
     */
    public String logoPath;
    public boolean silentMode = false;
    /**
     * the String to convert nbsp to; default is a single space, even when
     * multiple nbsps are together; use setNbsp("\\hspace*{5pt}") to retain a
     * space for each nbsp;
     */
    public String nbsp = null;
    /**
     * if true, horizontal margins are 1 centimeter smaller
     */
    public boolean smallerMargins = false;
    /**
     * value which will be added to level of output headings (may be negative).
     */
    public int headingLevelModifier = 0;
    /**
     * Maps template names to LaTeX commands (ie {{foo}} to \foo and
     * {{foo|bar|baz}} to \foo{bar}{baz}). Templates in this map are converted
     * to the mapped LaTeX command. See
     * <code>WikicodeConverter.convertTemplate(String wikicode)</code> for
     * usage priority.
     */
    private HashMap<String, String> templateMap = new HashMap<String, String>();
    /**
     * <p>
     * Sets the action performed on templates not handled by higher-priority
     * operations. (See <code>convertTemplate(String wikicode)</code> for
     * priorities.)
     * </p>
     * 
     * <p>
     * Possible actions:
     * </p>
     * <ul>
     * <li>"<b>ignore</b>": converts each "{" and "}" to LaTeX's "\{" and
     * "\}" and does nothing else</li>
     * <li>"<b>remove</b>": removes the complete template (ie "{{foo|bar}}"
     * become ""</li>
     * <li>"<b>removeExceptFirstargument</b>": removes the template except
     * the first argument (ie "{{foo|bar|baz}}" become "bar"</li>
     * <li>"<b>comment out</b>": comments out template (ie "{{foo}}" becomes
     * "\begin{comment}{{foo}}\end{comment}"</li>
     * <li>"<b>convert to command</b>": converts all templates to commands
     * (if command does not exist in LaTeX, adds command to style.sty with
     * template code)</li>
     * <li>"<b>expand</b>": (default) grabs wikicode for template online and
     * parses it</li>
     * </ul>
     */
    public TemplateAction templateAction = TemplateAction.commentOut;
    public SpanAction spanAction = SpanAction.commentOut;
    public DivAction divAction = DivAction.convertToBox;
    public ImageAction imageAction = ImageAction.convert;

    public enum TemplateAction {

        ignore, remove, removeExceptFirstargument, commentOut, convertToCommand, expand
        }

    public enum SpanAction {

        ignore, remove, commentOut
        }

    public enum DivAction {

        ignore, remove, commentOut, convertToBox
        }

    public enum ImageAction {

        ignore, remove, commentOutWikicode, convert, convertAndCommentOut
        }

    public void setIndent(String newIndent) {
        if (indent != null) {
            indent = newIndent;
        }
    }

    public String indent() {
        return indent;
    }

    public void setCodeLanguage(String codeLanguage) {
        if (codeLanguage != null) {
            this.codeLanguage = Util.getValidCodeLanguage(codeLanguage);

            if (this.codeLanguage == null) {
                Log.addError(codeLanguage + " is unsupported. Use one of these:\n\n" + Util.codeLanguages().toString());
            } else if (!this.codeLanguage.equals(codeLanguage)) {
                Log.addMessage(codeLanguage + " converted to " + Util.codeLanguageMap().get(codeLanguage));
            }
        }
    }

    public String codeLanguage() {
        return codeLanguage;
    }

    public void setBoldCommand(String newBoldCommand) {
        if (newBoldCommand != null) {
            newBoldCommand = newBoldCommand.replace("\\", "").replace("{", "");
            boldCommand = "\\" + newBoldCommand;
        }
    }

    public String boldCommand() {
        return boldCommand;
    }

    public void addImages(String... images) {
        for (String image : images) {
            //image = Util.toSafeFilename(image);
            if (image.length() > 4) {
                String ext = image.substring(image.length() - 4).toLowerCase();
                if (ext.equals("jpeg") || ext.equals(".jpg") || ext.equals(".png") || ext.equals(".svg") || ext.equals(".gif")) {
                    this.images.add(image);
                }
            } else {
                Log.addError("Could not add image " + image + " to set. Use format \"imagename.extension\" (ie: " + "\"foo.jpg\") and extenstion jpg, png, or svg.");
            }
        }
    }

    public Set<String> images() {
        return new HashSet<String>(images);
    }

    public void addToTemplateMap(String template, String command) {
        if (template != null && command != null) {
            template = template.replace("{{", "").replace("}}", "");
            if (template.contains("|")) {
                template = template.substring(0, template.indexOf("|"));
            }
            command = command.replace("\\", "");
            if (command.contains("{")) {
                command = command.substring(0, command.indexOf("{"));
            }

            templateMap.put(template, command);
        }
    }

    public HashMap<String, String> templateMap() {
        return new HashMap<String, String>(templateMap);
    }

    /**
     * @param action
     *            either "ignore", "remove", "remove except first argument",
     *            "comment out", "convert to command", or "expand"
     */
    public void setTemplateAction(String action) {
        if (action.equals("ignore")) {
            templateAction = TemplateAction.ignore;
        } else if (action.equals("remove")) {
            templateAction = TemplateAction.remove;
        } else if (action.equals("removeexceptfirstargument") || action.equals("remove except first argument")) {
            templateAction = TemplateAction.removeExceptFirstargument;
        } else if (action.equals("commentout") || action.equals("comment out")) {
            templateAction = TemplateAction.commentOut;
        } else if (action.equals("converttocommand") || action.equals("convert to command")) {
            templateAction = TemplateAction.convertToCommand;
        } else if (action.equals("expand")) {
            templateAction = TemplateAction.expand;
        }
    }

    /**
     * @param action
     *            either "ignore", "remove", or "comment out"
     */
    public void setSpanAction(String action) {
        if (action.equals("ignore")) {
            spanAction = SpanAction.ignore;
        } else if (action.equals("remove")) {
            spanAction = SpanAction.remove;
        } else if (action.equals("commentout") || action.equals("comment out")) {
            spanAction = SpanAction.commentOut;
        }
    }

    /**
     * 
     * @param action
     *            either "ignore", "remove", "comment out",  or "convert to box"
     */
    public void setDivAction(String action) {
        if (action.equals("ignore")) {
            divAction = DivAction.ignore;
        } else if (action.equals("remove")) {
            divAction = DivAction.remove;
        } else if (action.equals("commentout") || action.equals("comment out")) {
            divAction = DivAction.commentOut;
        } else if (action.equals("converttobox") || action.equals("convert to box")) {
            divAction = DivAction.convertToBox;
        }
    }

    /**
     * @param action
     *            either "ignore," "remove," "comment out wikicode," "convert,"
     *            or "convert and comment out"
     */
    public void setImageAction(String action) {
        if (action.equals("ignore")) {
            imageAction = ImageAction.ignore;
        } else if (action.equals("remove")) {
            imageAction = ImageAction.remove;
        } else if (action.equals("commentoutwikicode") || action.equals("comment out wikicode")) {
            imageAction = ImageAction.commentOutWikicode;
        } else if (action.equals("convert")) {
            imageAction = ImageAction.convert;
        } else if (action.equals("convertandcommentout") || action.equals("convert and comment out")) {
            imageAction = ImageAction.convertAndCommentOut;
        }
    }
}
